<template>
  <div class="form-edit-container">
    <div class="left-board">
      <el-tabs
        class="left-tabs"
        tab-position="left"
        v-model="leftTabActive"
      >
        <el-tab-pane name="components">
          <template #label>
            <span class="tabs-label">
              <el-icon size="24">
                <TablerCategory2 />
              </el-icon>
              <span>{{ $t("formgen.index.subject") }}</span>
            </span>
          </template>
          <el-scrollbar
            :height="`${wdHeight - 100}px`"
            class="left-scrollbar"
          >
            <div class="components-list">
              <div
                v-for="(item, listIndex) in leftComponents"
                :key="listIndex"
              >
                <div class="components-title">
                  {{ item.title }}
                </div>
                <VueDraggable
                  v-model="item.list"
                  :clone="handleCloneComponent"
                  :force-fallback="true"
                  :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
                  :animation="180"
                  :move="handleMove"
                  :scroll="true"
                  :scroll-sensitivity="0"
                  :sort="false"
                  class="components-draggable"
                  item-key="config.label"
                  @end="onEnd"
                >
                  <template
                    v-for="(element, index) in item.list"
                    :key="index"
                  >
                    <div class="components-item">
                      <div
                        class="components-body"
                        @click="addComponent(element)"
                      >
                        <form-svg-icon :name="element.config.tagIcon" />
                        {{ element.config.label }}
                      </div>
                    </div>
                  </template>
                </VueDraggable>
              </div>
            </div>
          </el-scrollbar>
        </el-tab-pane>
        <el-tab-pane name="outline">
          <template #label>
            <span class="tabs-label">
              <el-icon size="24">
                <TablerNotes />
              </el-icon>
              <span>{{ $t("formgen.index.outline") }}</span>
            </span>
          </template>
          <form-outline
            v-if="leftTabActive == 'outline'"
            :form-key="formKey"
            @scroll-to-field="handleFormScrollToField"
          />
        </el-tab-pane>
        <el-tab-pane class="questionBank">
          <template #label>
            <span class="tabs-label">
              <el-icon size="24">
                <TablerBook2 />
              </el-icon>
              <span>{{ $t("formgen.index.questionBank") }}</span>
            </span>
          </template>
          <FormQuestionTree @add="addComponent" />
        </el-tab-pane>
      </el-tabs>
    </div>
    <div class="center-board">
      <fast-toolbar />
      <language-selector @translation-success="handleTranslationSuccess" />
      <el-scrollbar
        ref="centerScrollbarRef"
        class="center-scrollbar"
        @scroll="handleContentScroll"
      >
        <div
          v-if="formConf"
          ref="centerRowsRef"
          class="center-board-row t-form-theme-wrap"
        >
          <div
            v-if="editFormInfo"
            class="form-desc-wrap"
          >
            <div class="center-name-box">
              <form-tinymce
                v-model:value="formConf.title"
                :inline="true"
                @change="handleSaveProjectInfo"
              />
            </div>
            <div class="center-desc-box">
              <form-tinymce
                v-model:value="formConf.description"
                :inline="true"
                @change="handleSaveProjectInfo"
              />
            </div>
            <div
              v-if="formConf.type == 4"
              class="evaluation-total-score"
            >
              <div class="total-score-title">{{ $t("formgen.index.total") }}</div>
              <div class="total-score">
                {{ totalScore }}
              </div>
            </div>
          </div>
          <async-loading v-if="loading" />
          <el-form
            :label-position="formConf.labelPosition"
            :label-width="formConf.labelWidth + 'px'"
            class="design-form"
            size="default"
            ref="designFormRef"
            :show-message="false"
            :status-icon="false"
          >
            <div
              v-if="!drawingList || !drawingList.length"
              class="empty-info"
            >
              <div>
                <img
                  src="@/assets/images/form/drag.png"
                  style="width: 247px"
                />
              </div>
              <div class="mt10">
                {{ $t("formgen.index.leftQuestion") }}
                {{ $t("formgen.index.drag") }}
              </div>
            </div>
            <VueDraggable
              v-model="drawingList"
              :animation="180"
              :force-fallback="true"
              :move="handleCenterMove"
              :scroll="true"
              :scrollSensitivity="160"
              class="drawing-board el-row"
              group="componentsGroup"
              handle=".mover"
              tag="el-row"
              @end="onItemEnd"
              :style="{
                'min-height': `${wdHeight - 280}px`
              }"
            >
              <template
                v-for="(element, index) in drawingList"
                :key="element.vModel"
              >
                <lazy-form-item-layout
                  :active-id="activeData?.vModel"
                  :current-item="element"
                  :index="index"
                  :class="[
                    'drawing-item',
                    currentPopoverItem?.vModel === element.config?.formId ? 'selected_border' : '',
                    activeData?.vModel === element.config?.formId ? 'active-from-item' : ''
                  ]"
                  @active-item="(item, parentItem) => activeFormItem(item, index, parentItem)"
                  @change="updateProjectItemInfo"
                  @change-label="changeLabel"
                  @copy-item="copyDrawingItem"
                  @delete-item="deleteDrawingItem"
                  @add-bank="handleAddToQuestionBank"
                  scroll-container=".center-scrollbar"
                />
              </template>
            </VueDraggable>
          </el-form>
        </div>
      </el-scrollbar>
    </div>
    <right-panel
      :active-data="activeData"
      :fields="drawingList"
      :form-conf="formConf"
      :show-field="!!drawingList.length"
      @add-fields="handleAddFields"
      @data-change="handleActiveDataChange"
    />
    <QuestionBankAddQuestion ref="addToQuestionBankRef" />
    <global-form-item-popover
      v-model:visible="popoverVisible"
      :virtual-ref="virtualElement"
      :current-item="currentPopoverItem"
      @copy="copyDrawingItem"
      @delete="deleteDrawingItem"
      @add-bank="handleAddToQuestionBank"
    />
  </div>
</template>
<script lang="ts" name="FormEditor" setup>
import { computed, nextTick, onBeforeMount, onDeactivated, onMounted, onUnmounted, provide, ref, watch } from "vue";
import { VueDraggable } from "vue-draggable-plus";
import { useRoute } from "vue-router";
import { useThrottleFn, useWindowSize } from "@vueuse/core";
import { cloneDeep, debounce } from "lodash-es";
import LazyFormItemLayout from "./content/LazyFormItemLayout.vue";
import RightPanel from "./right/RightPanel.vue";
import FormTinymce from "../tinymce/index.vue";
import FormSvgIcon from "../SvgIcon/index.vue";
import { useFormInfo } from "@/stores/formInfo";
import { formDesign } from "./hooks/useFormDesign";
import { useExamForm } from "./hooks/useExamForm";
import mittBus from "@/utils/mitt";
import { useComponents } from "./hooks/useComponents";
import { setThemeVars } from "@/views/formgen/utils/theme";
import { loadAsyncComponent } from "@/utils/asyncComponent";
import QuestionBankAddQuestion from "./QuestionBank/QuestionBankAddQuestion.vue";
import AsyncLoading from "@/components/TLoading/asyncLoading.vue";
import FastToolbar from "./fun/FastToolbar.vue";
import LanguageSelector from "./fun/LanguageSelector.vue";
import { operationHistory } from "./hooks/useOperationHistory";
import TablerCategory2 from "~icons/tabler/category-2";
import TablerBook2 from "~icons/tabler/book-2";
import TablerNotes from "~icons/tabler/notes";
import { useItemTinymceHook } from "@/views/formgen/components/FormDesign/FormItem/hooks/useItemTinymceHook";
import { useFormOptionEdit } from "@/views/formgen/components/FormDesign/FormItem/hooks/useFormOptionEdit";
import { resetTempLangContent } from "../../utils/formI18n";
import GlobalFormItemPopover from "./content/GlobalFormItemPopover.vue";
import { provideFormItemPopover } from "./hooks/useFormItemPopover";
import { useUserForm } from "@/views/formgen/components/GenerateForm/hooks/useUserForm";
import { USER_FORM_STATE_KEY } from "@/views/formgen/components/GenerateForm/types/constants";

const FormQuestionTree = loadAsyncComponent(() => import("./QuestionBank/FormQuestionTree.vue"));
const FormOutline = loadAsyncComponent(() => import("./fun/FormOutline.vue"));

const { setIsSaving } = useFormInfo();

const { height: wdHeight } = useWindowSize();

const {
  drawingList,
  activeData,
  activeIndex,
  formConf,
  formKey,
  loadData,
  syncAllItem,
  cloneComponent,
  createIdAndKey,
  activeFormItem,
  copyDrawingItem,
  updateProjectItemInfo,
  saveProjectItemInfo,
  queryProjectItems,
  isDefaultApi,
  checkFormPublishStatus,
  deleteDrawingItem,
  syncAllItemSorts,
  refreshAllItemSorts,
  activeSubformItem,
  currentLanguage
} = formDesign;

const { execute } = operationHistory;

const centerScrollbarRef = ref<any>(null);
const centerRowsRef = ref<HTMLDivElement>();

const { getAllComponents, getComponentsObj, getFormConfig } = useComponents();

const leftComponents = computed(() => {
  return getAllComponents(formType.value);
});

const formType = computed(() => {
  return formConf.value?.type;
});

const examFormHook = useExamForm();

const totalScore = computed(() => {
  return examFormHook.getTotalScore(drawingList.value);
});

const route = useRoute();

const handleSaveProjectInfo = debounce(() => {
  formDesign.saveProjectInfo();
}, 200);

const addToQuestionBankRef = ref<InstanceType<typeof QuestionBankAddQuestion> | null>(null);

const handleAddToQuestionBank = (item: any) => {
  addToQuestionBankRef.value?.showDialog(item);
};

const props = defineProps({
  /**
   * 是否编辑表单信息
   */
  editFormInfo: {
    type: Boolean,
    default: true
  },
  // 是否是默认表单编辑器 默认状态下走表单的接口 否则将不走任何接口
  isDefault: {
    type: Boolean,
    default: true
  }
});

const loading = ref(true);

onBeforeMount(() => {
  drawingList.value = [];
});

const leftTabActive = ref("components");

onMounted(async () => {
  setThemeVars(null);
  isDefaultApi.value = props.isDefault;
  if (props.isDefault) {
    formKey.value = route.query.key as string;
    formConf.value = cloneDeep(getFormConfig((route.query.type as any) || 1));
    formConf.value!.formKey = formKey.value;
    await loadData();
  }
  loading.value = false;
});

onUnmounted(() => {
  handleLeave();
  currentLanguage.value = "zh-CN";
});

onDeactivated(() => {
  handleLeave();
});

// 离开页面时
const handleLeave = () => {
  if (props.isDefault) {
    refreshAllItemSorts();
  }
  activeData.value = null;
  activeIndex.value = -1;
};

mittBus.on("refreshFormList", () => {
  queryProjectItems();
});

const handleActiveDataChange = async (val: any) => {
  // 特殊处理自增表单 使修改的数据为自增表单组件本身
  let newVal = cloneDeep(val);
  if (val.isChild && activeSubformItem.value) {
    // 如果是子表单 找到子表单里面这个组件修改他
    activeSubformItem.value.childList.forEach((item: any, index: number) => {
      if (item.vModel === val.vModel) {
        activeSubformItem.value!.childList[index] = cloneDeep(newVal);
        return;
      }
    });
    newVal = cloneDeep(activeSubformItem.value);
  }
  console.log(newVal);
  updateProjectItemInfo(newVal);
};

const changeLabel = (currentItem: any, value: any) => {
  console.log("----", currentItem, value);
};

const handleMove = () => {
  console.log(formConf.value?.status);
  if (formConf.value?.status == 2) {
    checkFormPublishStatus();
    return false;
  }
  return true;
};

const handleCloneComponent = (obj: any) => {
  execute(drawingList.value);
  return cloneComponent(obj);
};

const onEnd = (obj: any) => {
  if (obj.from !== obj.to) {
    activeIndex.value = obj.newIndex;
    activeData.value = drawingList.value[obj.newIndex];
    // 拖拽到自增表单不单独保存
    if (obj.to.className.indexOf("list-main") > -1) {
      return;
    }
    saveProjectItemInfo(activeData.value).then(() => {
      onItemEnd(obj, true);
    });
  }
};
const handleCenterMove = (obj: any) => {
  execute(drawingList.value);
  // 不允许拖动到子表单区域
  if (obj.to.className === "list-main") {
    return false;
  }
};

const onItemEnd = (obj: any, createNew = false) => {
  setIsSaving(true);
  // createNew 避免新的组件拉到第一个不排序
  if (obj.oldIndex === obj.newIndex && !createNew) {
    setIsSaving(false);
    return;
  }
  syncAllItemSorts();
};

const addComponent = (item: any) => {
  checkFormPublishStatus().then((result: boolean) => {
    if (result) {
      const clone = cloneComponent(item);
      execute(drawingList.value);
      saveProjectItemInfo(clone).then(() => {
        drawingList.value.push(clone);
        activeFormItem(clone, drawingList.value.length - 1);
        scrollToBottom();
      });
    }
  });
};

const scrollToBottom = () => {
  nextTick(() => {
    centerScrollbarRef.value.setScrollTop(centerRowsRef.value!.clientHeight);
  });
};

const designFormRef = ref<any>(null);

const handleFormScrollToField = (prop: string) => {
  designFormRef.value.scrollToField(prop);
};

const handleContentScroll = useThrottleFn(() => {
  hidePopover();
  window.tinymce.activeEditor.getElement()?.blur();
}, 1000);

/**
 * 新增字段 ocr组件使用
 * @param val
 */
const handleAddFields = (val: any) => {
  console.log("change");
  let fieldMapping: any = {};
  Object.keys(val).forEach((key, index) => {
    let field = val[key] as any;
    let compo = cloneDeep(getComponentsObj()[field.type]);
    compo.config.label = field.label;
    let clone = cloneComponent(compo);
    clone = createIdAndKey(clone, index);
    console.log(clone);
    drawingList.value.push(clone);
    fieldMapping[key] = clone.config.formId;
  });
  activeData.value!.fieldMapping = fieldMapping;
  console.log(fieldMapping);
  handleActiveDataChange(activeData.value);
  syncAllItem();
};

// 选项富文本处理
const { changeOptionLabel } = useFormOptionEdit();
const { initTinymce } = useItemTinymceHook(changeOptionLabel);

watch(
  () => activeData.value?.vModel,
  val => {
    console.log(val);
    if (val && (val.startsWith("radio") || val.startsWith("checkbox"))) {
      if (val && activeData.value?.config?.options && activeData.value?.config?.optionsType == 0) {
        console.log("init tinymce  ." + activeData.value?.vModel);
        nextTick(() => {
          initTinymce(val || "", (editors: any) => {
            // 某些情况下初始化失败 在尝试一次
            if (!editors || !editors?.length) {
              setTimeout(() => {
                initTinymce(val || "", () => {});
              }, 1000);
            }
          });
        });
      }
    }
  }
);

const handleTranslationSuccess = async (data: any) => {
  console.log(data);
  currentLanguage.value = data.langCode;
  resetTempLangContent();
  await loadData();
};
const userFormStore = useUserForm();
provide(USER_FORM_STATE_KEY, userFormStore);
// 提供 popover 状态
const { popoverVisible, virtualElement, currentPopoverItem, hidePopover } = provideFormItemPopover();
</script>

<style lang="scss">
@use "../../assets/styles/home.scss" as *;
@use "../../assets/styles/right.scss" as *;

.form-edit-container {
  .components-draggable,
  .drawing-board {
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
  }

  .item-popover {
    .popover-content {
      .title {
        font-size: 14px;
        font-weight: bold;
        margin-bottom: 8px;
      }

      .desc {
        font-size: 12px;
        color: #666;
      }
    }
  }
}
</style>
